package push

import (
	"bytes"
	"encoding/json"
	"gitee.com/yysf_xin/dplog/pkg/slog"
	"gitee.com/yysf_xin/go-common/tools"
	"io"
	"net/http"
	"strconv"
	"time"
)

type Http struct {
	Url      string
	Client   *http.Client
	errCount int
	last     time.Time
	channel  chan *MsgRef
}

func NewHttp(url string) *Http {
	return &Http{
		Url: url,
		Client: &http.Client{
			Timeout: 2 * time.Second,
		},
		last:    time.Now(),
		channel: make(chan *MsgRef, 10),
	}
}

func (h *Http) Run() {
	for {
		m := <-h.channel
		h.notify(m)
	}
}

func (h *Http) DoNotify(m *MsgRef) {
	if h.errCount > 5 && time.Now().Sub(h.last) < 5*time.Second {
		tools.Log.Println("not notify errCount", h.errCount)
		return
	}
	m.Ref.Retain()
	h.channel <- m
}

func (h *Http) notify(m *MsgRef) {
	defer m.Ref.Release()
	buff := slog.BufPool.Get().(*bytes.Buffer)
	defer slog.BufPool.Put(buff)
	buff.Reset()
	err := json.NewEncoder(buff).Encode(&m.Msg)
	if err != nil {
		tools.Log.Println(err)
		return
	}

	resp, err := h.Client.Post(h.Url, "application/json", buff)
	if resp != nil && resp.Body != nil {
		defer resp.Body.Close()
	}
	if err != nil || resp.StatusCode != 200 {
		tools.Log.Println(err)
		h.errCount++
		h.last = time.Now()
		return
	}
	h.errCount = 0
	if m.MsgId == 0 {
		buff.Reset()
		_, err = io.Copy(buff, resp.Body)
		if err != nil {
			tools.Log.Println(err)
		} else {
			var id int
			id, err = strconv.Atoi(buff.String())
			if err != nil {
				tools.Log.Println(err)
			} else {
				m.MsgId = uint(id)
			}
		}
	}

}
